package pl.drypisy;

import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.StrictMode;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

/** 
 * route list from db and from FTP
 * loads route from XML file
 * downloads and loads route from FTP server
 * deletes route from db
 * @author Michal Drobniak
 */
public class BrowserActivity extends Activity {
	
	private static final int PICKFILE_RESULT_CODE = 1;
	
	private ArrayList<String> route;				//route data from xml and from ftp, used in saveRouteInBase()
	private ArrayList<HashMap<String, String>> ch;  //list of checkpoint's maps from xml and from ftp, used in saveRouteInBase()
	
	private DBAdapter db;
	
	private ProgressBar progressBar; //showed on download process from ftp
	private TextView browserTw1;	//says what to do with list items
	
	private ListView routeList;		//routes list from db
	private ListView ftpRouteList=null;   //routes list from ftp
	private ArrayAdapter<RouteData> routeListAdapter; //list adapter
	private ArrayAdapter<RouteData> ftpRouteListAdapter; //list adapter
	
	private String routeTitle;	//when downloading route data from ftp, 
								//used in onItem listener->downloadRouteDialogLstr
	private AlertDialog.Builder dialogBuilder;  //confirmation of downloading a route (download/cancel)
	
	private Dialog aboutDialog;	//about route
	
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.browser);
        
        //hides activityHeader in landscape position
        WindowManager wm=getWindowManager();
        Display d=wm.getDefaultDisplay();
        if(d.getWidth()>d.getHeight()){
        	findViewById(R.id.activityHeader).setVisibility(View.GONE);
        }
        
        db=new DBAdapter(this); // Database
        
        /**
         * add from XML Button
         */
        Button addRouteFromXmlBtn=(Button) findViewById(R.id.browserAddRouteBtn);
        addRouteFromXmlBtn.setOnClickListener(new View.OnClickListener() {
        	
        	public void onClick(View v) {
				Intent intent = new Intent();
	            intent.setType("file/*");
	            intent.setAction(Intent.ACTION_GET_CONTENT);
	            startActivityForResult(Intent.createChooser(intent,"Wybierz plik xml"), PICKFILE_RESULT_CODE);
			}
		});
        
        //browserTw1
        browserTw1=(TextView) findViewById(R.id.browserTw1);
        
        /**
         * add from FTP Button
         * if routeList is visible than hides it and shows ftpRouteList (and vice versa)
         * if ftpRouteList has set adapter (it was downloaded before) just shows it, doesn't download again
         */
        final Button addRouteFromFTPBtn=(Button) findViewById(R.id.browserAddRouteFromFtpBtn);
        addRouteFromFTPBtn.setOnClickListener(new View.OnClickListener() {
        	
        	public void onClick(View v) {
        		//check for internet conneciton
            	if(!isOnline()){
            		Toast.makeText(getBaseContext(), R.string.browserActvInternetConnectionWarning, Toast.LENGTH_SHORT).show();
            		return;
            	}
        		if(routeList.getVisibility()==View.VISIBLE){
        			routeList.setVisibility(View.GONE);
            		ftpRouteList.setVisibility(View.VISIBLE);
            		if(ftpRouteList.getAdapter()==null){
            			new DownloadRouteListFTP().execute(""); //<---------
            		}
            		
            		browserTw1.setText(R.string.browserTw1onFtp);
            		addRouteFromFTPBtn.setText(R.string.browserAddRouteFromFtpBtnVisible);
        		} else {
        			routeList.setVisibility(View.VISIBLE);
            		ftpRouteList.setVisibility(View.GONE);
            		printRoutes();
            		browserTw1.setText(R.string.browserTw1);
        			addRouteFromFTPBtn.setText(R.string.browserAddRouteFromFtpBtn);
        		}
        	}
		});
        
        //progress bar
        progressBar=(ProgressBar) findViewById(R.id.ftpRouteListProgressBar);
        
        /**
         * shows route list
         * listens for onItemClick and shows context menu
         */
        routeList = (ListView) findViewById(R.id.routeList);
        routeList.setOnItemClickListener(new OnItemClickListener() {

			public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
				view.showContextMenu();
			}
		});
        
        /**
         * shows ftp route list
         * download route on click
         */
        ftpRouteList = (ListView) findViewById(R.id.ftpRouteList);
        ftpRouteList.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
				dialogBuilder=new AlertDialog.Builder(BrowserActivity.this);
				dialogBuilder.setMessage(R.string.browserDownloadDialogMsg)
					.setPositiveButton(R.string.browserDownloadDialogPositive, downloadRouteDialogListener)
					.setNegativeButton(R.string.browserDownloadDialogNegative, downloadRouteDialogListener)
					.show();
					
				//route's title used in downloadRouteDialogListener -> downloadRouteData as fileName
				TextView routeTitleView = (TextView) view.findViewById(R.id.routeTitle);
				routeTitle = (String) routeTitleView.getText(); 
			}
		});
        
        //PRINTS ROUTE LIST
        printRoutes(); //<------------
    }
    
    /**
	 * gets xml file path from users phone
     */
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            if (requestCode == PICKFILE_RESULT_CODE) {
                String path = data.getData().getPath();
                getXMLData(path);  //parsing choosen file <----------
                printRoutes();
                
            }
        }
    }
    
    /**
     * @param inputStream from file downloaded from ftp
     * fills route array
     * fills array of checkpoints maps
     * saves in db
     * used in DownloadRouteDataFTP class
     */
    private long getXMLDataFromInputStream(InputStream is){
    	XMLParser xml=new XMLParser(is);	//parse for input stream
        route= xml.getRouteData();	//fill array with route data
        ch = xml.getCheckpoints();	//fill array with checkpoint's maps
        
        return saveRouteInBase();  //save into database <-----------
        						   //return for AsyncTask
    }
    
    /**
     * @param path to xml file on users phone
	 * fills route array
	 * fills array of checkpoints maps
	 * saves in db
	 * used in onActivityResult
	 */
	private void getXMLData(String path){
		XMLParser xml=new XMLParser(path);
	    route= xml.getRouteData();	//fill array with route data
	    ch = xml.getCheckpoints();	//fill array with checkpoint's maps
	    
	    saveRouteInBase();  //save into database <-----------
	}

	/**
     * used to save data about route and checkpoints in db
     * opens db when necessary
     * @return status of inserting to db, used cause of AsyncTask class - DownloadRouteDataFTP
     */
    private long saveRouteInBase(){
    	DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    	Calendar cal = Calendar.getInstance();
    	String date = dateFormat.format(cal.getTime());
    	long insertState=0;
        
    	db.open();
    	//Log.d("db save route in base", route.toString());
    	//Log.d("db",route.get(0)+" "+route.get(1) +" "+date);
        long routeId = db.insertRoute(route.get(0),route.get(1),date);
        
        for(int i=0;i<ch.size();i++){
        	insertState=
        	db.insertCheckpoint(
        			routeId, ch.get(i).get("name"),    //route_id,name
        			ch.get(i).get("lat"),  ch.get(i).get("lon"),  //lat,lon
        			ch.get(i).get("task"), ch.get(i).get("answer"), 	//task,answer
        			ch.get(i).get("hint1"), ch.get(i).get("hint2"), ch.get(i).get("hint3"), ch.get(i).get("answer")); //hints
        	
        	/*Log.d("saveInRoute","inserted checkpoint "+i + " hints:" +
        			" "+ ch.get(i).get("hint1")+
        			" "+ch.get(i).get("hint2")+
        			" "+ch.get(i).get("hint3")+
        			" "+ch.get(i).get("answer"));
        	*/	
        }
    	db.close();
        return insertState;
    }
    
    /**
     * prints routes list
     * opens db
     */
    private void printRoutes(){
    	db.open();
        Cursor c = db.getAllRoutes();
        
        ArrayList<RouteData> routes=new ArrayList<RouteData>();
        
        if(c.moveToFirst()){
        	do { //id,title,date,about
        		routes.add(new RouteData(Integer.parseInt(c.getString(0)),
        				c.getString(1), c.getString(3) ,c.getString(2))); 
        	} while(c.moveToNext());
        }
        db.close();
        //inflater
        LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        //set adapter to list
        routeListAdapter = new RouteListAdapter(getApplicationContext(), R.layout.route_list, routes,vi);
        routeList.setAdapter(routeListAdapter);
        registerForContextMenu(routeList);
    }
    
    /**
     * checks for internet connection
     * required for ftp connection
     * @return true if users got connection
     */
    private boolean isOnline() {
        ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

        NetworkInfo netInfo = cm.getActiveNetworkInfo();
        if (netInfo != null && netInfo.isConnectedOrConnecting()) {
            return true;
        }
        return false;
    }
    
    
    /**
     * deletes route by ID
     * opens db
     */
    private boolean deleteRoute(int routeId){
    	db.open();
    	boolean del = db.deleteRoute(routeId);
    	db.close();
    	if(del){
    		printRoutes();
    	}
    	return del;
    }
    
    
    /*=============CONTEXT MENU=================*/
    
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo){
    	super.onCreateContextMenu(menu, v, menuInfo);
    	menu.add(0,0,0,R.string.browserContextMenuOptionAbout);
    	menu.add(0,1,1,R.string.browserContextMenuOptionDelete);
    }
    
    public boolean onContextItemSelected(MenuItem item){
    	return routeChoiceMenu(item);
    }
    
    /*
     * Choice menu
     *  0 - more about a route
     *  1 - delete route
     */
    public boolean routeChoiceMenu(MenuItem item){
    	AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
    	View itemView=info.targetView;
    	int routeId=(Integer) info.targetView.getTag();
    	
    	switch(item.getItemId()){
	    	case 0:
	    		setAboutDialog(itemView);
	    		aboutDialog.show();
	    		return true;
	    	case 1:
	    		Toast.makeText(this, "Route deleted", Toast.LENGTH_SHORT).show();
	    		deleteRoute(routeId);
	    		return true;
    	}
    	return false;
    }
    
    /**
     * shows dialog with full description of route
     */
    private void setAboutDialog(View itemView){
    	TextView aboutView=(TextView) itemView.findViewById(R.id.routeAbout);
    	TextView titleView=(TextView) itemView.findViewById(R.id.routeTitle);
    	
    	aboutDialog=new Dialog(BrowserActivity.this);
		aboutDialog.setContentView(R.layout.about_dialog);
		aboutDialog.setTitle(titleView.getText());
		
		TextView aboutDialogAbout=(TextView) aboutDialog.findViewById(R.id.aboutDialogAbout);
		aboutDialogAbout.setText(aboutView.getText());
		Button aboutDialogBtn=(Button) aboutDialog.findViewById(R.id.aboutDialogOk);
		aboutDialogBtn.setOnClickListener(new OnClickListener() {
			
			public void onClick(View v) {
				aboutDialog.cancel();
			}
		});
    }
    
    /**
     * decision DIALOG listener
     * decides to download route data
     */
    DialogInterface.OnClickListener downloadRouteDialogListener=new DialogInterface.OnClickListener() {
		
  		public void onClick(DialogInterface dialog, int which) {
  			switch(which){
  				case DialogInterface.BUTTON_POSITIVE:
  					db.open();
  						new DownloadRouteDataFTP().execute(routeTitle);
  					db.close();
  					break;
  				case DialogInterface.BUTTON_NEGATIVE:
  					break;
  			}
  		}
  	};
    
    /*==========================================*/
    
    /**
     * inner class
     * process downloading of route LIST in Thread - by AsyncTask class
     */
    class DownloadRouteListFTP extends AsyncTask<String, Void, ArrayList<RouteData>> {
    	
		protected ArrayList<RouteData> doInBackground(String... pB) {
			return downloadFtpRoutes();
		}
		
		protected void onPreExecute() {
			progressBar.setVisibility(View.VISIBLE);
		}
		
		protected void onPostExecute(ArrayList<RouteData> c) {
			ArrayList<RouteData> routes=new ArrayList<RouteData>();
			
	        for(RouteData route : c){
	        	routes.add(route);
	        }
	        //inflater
	        LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
	        //set adapter to list
	        ftpRouteListAdapter = new RouteListAdapter(getApplicationContext(), 
	        											R.layout.route_list, routes, vi);
	        progressBar.setVisibility(View.GONE);
	        ftpRouteList.setAdapter(ftpRouteListAdapter);
		}
		
		/*
	     * download route list from ftp and return Array of routeNames
	     */
	    private ArrayList<RouteData> downloadFtpRoutes(){
	    	StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
	        StrictMode.setThreadPolicy(policy); 
	       
	    	FTPAdapter ftp=new FTPAdapter();
	        ArrayList<RouteData> c= ftp.downloadList(); //<----------
	        
			return c;
	    }
    }
    
    /**
     * inner class
     * download specific route DATA in Thread - by AsyncTask
     */
    class DownloadRouteDataFTP extends AsyncTask<String, Void, Long>{

		@Override
		protected Long doInBackground(String... params) {
			String routeTitle=params[0];
			return downloadAndSaveInBaseRouteData(routeTitle);
		}
		
		protected void onPreExecute() {
			progressBar.setVisibility(View.VISIBLE);
			ftpRouteList.setEnabled(false);
		}
		
		protected void onPostExecute(Long l) {
			progressBar.setVisibility(View.GONE);
			ftpRouteList.setEnabled(true);
			//ftpRouteList.setVisibility(View.GONE);
			//routeList.setVisibility(View.VISIBLE);
			//addRouteFromFTPBtn.setText(R.string.browserAddRouteFromFtpBtn);
			Toast.makeText(getBaseContext(), "Dodano nową trasę", Toast.LENGTH_LONG).show();
		}
    
		/*
		 * download
		 * parse 
		 * save in base
		 */
		private long downloadAndSaveInBaseRouteData(String routeTitle){
	    	FTPAdapter ftp=new FTPAdapter();
	    	
	    	InputStream is = ftp.downloadRoute(routeTitle);
	    	long insertState=getXMLDataFromInputStream(is);
			return insertState;
	    }
    }
    
    /*
     * only debug
     */
   /*  private String printCheckpoints(){
    	String output="";
    	db.open();
        Cursor c = db.getAllCheckpoints();
        if(c.moveToFirst()){
        	do {
        		output+=c.getString(0) +" "+ c.getString(1) +" "+c.getString(2) +" "+ c.getString(3) +
        				" "+ c.getString(4) +" "+ c.getString(5) +" "+ c.getString(6)
        				+ c.getString(7) +" "+ c.getString(8) +" "+ c.getString(9) +" "+ c.getString(10)+"\n";
        	} while(c.moveToNext());
        }
        db.close();
        
        Log.d("ch", output);
        return output;
    }
    }*/
    
}

